home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 28 / develop issue 28 code / sketch / source / adts / documentadt.c next >
Encoding:
C/C++ Source or Header  |  1996-08-03  |  17.6 KB  |  635 lines

  1. /****************************************************************************
  2.  * 
  3.  * DocumentADT.c
  4.  * 
  5.  * Functions related to the Document Abstract Data Type
  6.  *
  7.  ****************************************************************************/
  8.  
  9. #include "Structs.h"
  10.  
  11. #include "Assertion.h"
  12. #include "DocumentADT.h"
  13. #include "ElementADT.h"
  14.  
  15. #include "StringUtils.h"
  16.  
  17. // -----------------------------------------------------------------------------------
  18. #pragma mark                         PRIVATE CONSTANTS
  19. // -----------------------------------------------------------------------------------
  20.  
  21. static const short            kLockDocumentReferences            = true;
  22.  
  23.  
  24. // -----------------------------------------------------------------------------------
  25. #pragma mark                         PRIVATE VARIABLES
  26. // -----------------------------------------------------------------------------------
  27.  
  28. static DocumentList            fgDocumentList        = nil;
  29. static OSErr                    fgError                = noErr;
  30. static short                    fgDocumentNumber    = 0;
  31.  
  32.  
  33. // -----------------------------------------------------------------------------------
  34. #pragma mark                         PRIVATE PROTOTYPES
  35. // -----------------------------------------------------------------------------------
  36. static OSErr                    CreateDocumentData                (DocumentReference document, DocumentType documentType);
  37. static void                        FreeDocumentData                    (DocumentReference document);
  38. static void                        FreeDocument                        (DocumentReference document);
  39. static void                        SetDocumentStructID                (DocumentReference document);
  40. static void                        SetDocumentNumber                    (DocumentReference document, short documentNumber);
  41. static Boolean                    DocumentListIsValid                (DocumentList list);
  42. static Boolean                    DocumentIsValid                    (DocumentReference document);
  43. static Boolean                    IsEmpty                                (DocumentList list);
  44. static void                        Insert                                (DocumentList list, DocumentReference documentToInsert);
  45. static void                        Remove                                (DocumentReference document);
  46. static void                        Link                                    (DocumentReference previous, DocumentReference next);
  47.  
  48. /*****************************************************************************
  49.  * 
  50.  * DocumentError                                                        PUBLIC
  51.  *
  52.  * Call to get the last error registered by the ADT
  53.  * 
  54.  *****************************************************************************/
  55. OSErr DocumentError(void)
  56. {
  57.     return fgError;
  58. }
  59.  
  60.  
  61. /*****************************************************************************
  62.  * 
  63.  * GetDocumentList                                                      PUBLIC
  64.  * 
  65.  * Returns the document list reference which is a static global local to the
  66.  * document ADT.
  67.  *
  68.  *****************************************************************************/
  69. DocumentList GetDocumentList(void)
  70. {
  71.     return fgDocumentList;
  72. }
  73.  
  74.  
  75. /*****************************************************************************
  76.  * 
  77.  * CreateDocumentList                                                    PUBLIC
  78.  *
  79.  * Call during program startup time
  80.  * 
  81.  *****************************************************************************/
  82. void CreateDocumentList(void)
  83. {
  84.     Boolean             success    = false;
  85.     DocumentList    head        = nil;
  86.     
  87.     
  88.     head        = (DocumentList) NewHandleClear(sizeof(DocumentRecord));
  89.     fgError    = MemError();
  90.     
  91.     success = ((head != nil) && (fgError == noErr));
  92.     
  93.     if (success) 
  94.     {
  95.         if (kLockDocumentReferences)
  96.             HLockHi((Handle)head);
  97.  
  98.         (**head).structID = kDocumentListID;
  99.     }
  100.     
  101.     fgDocumentList = head;
  102. }
  103.  
  104.  
  105. /*****************************************************************************
  106.  * 
  107.  * CreateDocument                                                       PUBLIC
  108.  *
  109.  * Call to create a new document structure in memory - usually on New or Open
  110.  * In the case of open, you will need to initialize fields in your client code
  111.  * 
  112.  *****************************************************************************/
  113. DocumentReference CreateDocument(DocumentList list, DocumentType documentType)
  114. {
  115.     OSErr                        error;
  116.     DocumentReference        document;
  117.     
  118.     document = (DocumentReference) NewHandleClear(sizeof (DocumentRecord));
  119.     error        = MemError();
  120.     
  121.     if (error == noErr)                                                                                // Initialize all heap internal data here
  122.     {
  123.         if (kLockDocumentReferences)
  124.             HLockHi((Handle) document);
  125.  
  126.         SetDocumentStructID(document);
  127.         SetDocumentNumber(document, ++fgDocumentNumber);
  128.         SetDocumentType(document,         documentType);    
  129.         
  130.         error = CreateDocumentData(document, documentType);
  131.     }
  132.         
  133.  
  134.     if (error == noErr)                                                                                // insert the new record into the list
  135.         Insert(list, document);
  136.     else
  137.     {
  138.         FreeDocumentData(document);
  139.         FreeDocument(document);
  140.     }
  141.     
  142.     fgError = error;
  143.     
  144.     return document;
  145. }
  146.  
  147.  
  148. /*****************************************************************************
  149.  * 
  150.  * CountDocuments                                                        PUBLIC
  151.  * 
  152.  * Returns the number of documents contained in a specified document list.
  153.  *
  154.  *****************************************************************************/
  155. short CountDocuments(DocumentList list)
  156. {
  157.     DocumentReference     document = nil;
  158.     short                        count        = 0;
  159.     
  160.     if (DocumentListIsValid(list))
  161.     {
  162.         document = GetFirstDocument(list);
  163.  
  164.         while (document != nil && DocumentIsValid(document))
  165.         {
  166.             count++;
  167.             document = GetDocumentNextDocument(document);
  168.         }
  169.     }
  170.     
  171.     return count;
  172. }
  173.  
  174.  
  175. /*****************************************************************************
  176.  * 
  177.  * DestroyDocumentList                                                  PUBLIC
  178.  *
  179.  * Call at program shutdown time to delete all documents, from head to tail
  180.  * 
  181.  *****************************************************************************/
  182. void DestroyDocumentList(DocumentList list)
  183. {
  184.     DocumentReference        document;
  185.  
  186.     if (DocumentListIsValid(list))
  187.     {
  188.         document    = GetFirstDocument(list);
  189.         
  190.         while (document != nil)
  191.         {
  192.             DestroyDocument(document);
  193.             document    = GetFirstDocument(list);
  194.         }
  195.  
  196.         DisposeHandle((Handle)list);        
  197.     }
  198. }
  199.  
  200.  
  201. /*****************************************************************************
  202.  * 
  203.  * DestroyDocument                                                      PUBLIC
  204.  *
  205.  *  Call when an document document is closed
  206.  * 
  207.  *****************************************************************************/ 
  208. void DestroyDocument(DocumentReference document)
  209. {
  210.     if (DocumentIsValid(document)) 
  211.     {
  212.         Remove(document);
  213.         FreeDocumentData(document);
  214.         FreeDocument(document);
  215.     }
  216. }
  217.  
  218.  
  219. /*****************************************************************************
  220.  * 
  221.  * GetFirstDocument                                                     PUBLIC
  222.  *
  223.  * Call to get a reference to the first document in an document list
  224.  *    Use with GetNextDocument() to walk the document list
  225.  * 
  226.  *****************************************************************************/
  227. DocumentReference GetFirstDocument(DocumentList list)
  228. {
  229.     DocumentReference head  = (DocumentReference)list;
  230.     DocumentReference first = nil;
  231.     
  232.     if (DocumentListIsValid(list))
  233.     {
  234.          first = (**head).next;
  235.     }
  236.  
  237.     return first;
  238. }
  239.  
  240.  
  241. /*****************************************************************************
  242.  * 
  243.  * GetLastDocument                                                      PUBLIC
  244.  *
  245.  * Call to get a reference to the last document in an document list
  246.  * 
  247.  *****************************************************************************/
  248. DocumentReference GetLastDocument(DocumentList list)
  249. {
  250.     DocumentReference last = GetFirstDocument(list);
  251.  
  252.     if (last != nil) {
  253.         while (GetDocumentNextDocument(last) != nil) {
  254.           last = GetDocumentNextDocument(last);
  255.         }
  256.     }
  257.     
  258.     return last;
  259. }
  260.  
  261.  
  262. /*****************************************************************************
  263.  * 
  264.  * CreateDocumentData                                                  PRIVATE
  265.  * 
  266.  * Set up a new document record with reasonable values.
  267.  *
  268.  * It is the responsibility of the caller to populate the window reference.
  269.  *
  270.  *****************************************************************************/
  271. static OSErr CreateDocumentData(DocumentReference document, DocumentType documentType)
  272. {
  273. #pragma unused (documentType)
  274.  
  275.     OSErr                    error                = noErr;
  276.     ElementList       list;
  277.     
  278.     SetDocumentNumberOfChanges (document,  0);
  279.     SetDocumentMaxWidth            (document,  600);
  280.     SetDocumentMaxHeight            (document,  300);
  281.  
  282.     list = CreateElementList();
  283.     
  284.     if (list != nil)
  285.         SetDocumentElementList(document, list);
  286.     else
  287.         error = memFullErr;
  288.     
  289.  
  290.     return error;
  291. }
  292.  
  293.  
  294. /*****************************************************************************
  295.  * 
  296.  * FreeDocumentData                                                    PRIVATE
  297.  * 
  298.  * Dispose of all memory allocated and stored inside this document, but not
  299.  * the document itself
  300.  *
  301.  *****************************************************************************/
  302. static void FreeDocumentData(DocumentReference document)
  303. {
  304.     WindowPtr    window;
  305.     
  306.     window = GetDocumentWindow(document);
  307. //    if (window != nil)
  308. //        HideWindow(window);
  309.  
  310.     SetDocumentWindow(document, nil);  // This disposes of the existing window
  311. }
  312.  
  313.  
  314. /*****************************************************************************
  315.  * 
  316.  * FreeDocument                                                        PRIVATE
  317.  * 
  318.  * Dispose the document record. You should have already called
  319.  * FreeDocumentData() on the document.
  320.  *
  321.  *****************************************************************************/
  322. static void FreeDocument(DocumentReference document)
  323. {
  324.     if (DocumentIsValid(document))
  325.     {
  326.         if (kLockDocumentReferences == true)
  327.             HUnlock((Handle)document);
  328.  
  329.         DisposeHandle((Handle)document);
  330.     }
  331. }
  332.  
  333.  
  334. /*****************************************************************************
  335.  * 
  336.  * SetDocumentStructID                                                 PRIVATE
  337.  * 
  338.  *  For debugging, we store a "magic cookie" in the first data member
  339.  *
  340.  *****************************************************************************/
  341. static void SetDocumentStructID(DocumentReference document)
  342. {
  343.     (**document).structID = kDocumentRecordID;
  344. }
  345.  
  346.  
  347. /*****************************************************************************
  348.  * 
  349.  * SetDocumentNumber                                                   PRIVATE
  350.  * 
  351.  * Assign a sequential number for all documents created.
  352.  *
  353.  *****************************************************************************/
  354. static void SetDocumentNumber(DocumentReference document, short documentNumber)
  355. {
  356.     (**document).documentNumber = documentNumber;
  357. }
  358.  
  359.  
  360. /*****************************************************************************
  361.  * 
  362.  * DocumentListIsValid                                                 PRIVATE
  363.  * 
  364.  * Returns true if specified document list is valid. This is useful for debugging.
  365.  *
  366.  *****************************************************************************/
  367. static Boolean DocumentListIsValid(DocumentList list)
  368. {
  369.     DocumentReference        head        = (DocumentReference) list;
  370.     Boolean                    isValid    = (head != nil);
  371.     
  372.     if (isValid)
  373.     {
  374.       isValid = ((**head).structID == kDocumentListID);
  375.     }
  376.     
  377.     Assert(isValid, "An invalid document list has been detected.");
  378.     
  379.     return isValid;
  380. }
  381.  
  382.  
  383. /*****************************************************************************
  384.  * 
  385.  * DocumentIsValid                                                     PRIVATE
  386.  * 
  387.  * returns true if specified document is valid. This is useful for debugging.
  388.  *
  389.  *****************************************************************************/
  390. static Boolean DocumentIsValid(DocumentReference document)
  391. {
  392.     Boolean isValid = (document != nil);
  393.     
  394.     if (isValid)
  395.       isValid = ((**document).structID == kDocumentRecordID);
  396.     
  397.     Assert(isValid, "An invalid document has been detected.");
  398.     
  399.     return isValid;
  400. }
  401.  
  402. /*****************************************************************************
  403.  * 
  404.  * IsEmpty                                                             PRIVATE
  405.  * 
  406.  * Returns true if the list contains no documents
  407.  *
  408.  *****************************************************************************/
  409. static Boolean IsEmpty(DocumentList list)
  410. {
  411.     return GetFirstDocument(list) == nil;
  412. }
  413.  
  414.  
  415. /*****************************************************************************
  416.  * 
  417.  * Insert                                                              PRIVATE
  418.  * 
  419.  * Insert a document into the list, implemented by appending the document.
  420.  *
  421.  *****************************************************************************/
  422. static void Insert(DocumentList list, DocumentReference documentToInsert)
  423. {
  424.     DocumentReference        document;
  425.     
  426.     if (IsEmpty(list))
  427.         document = (DocumentReference) list;
  428.     else
  429.         document = GetLastDocument(list);
  430.  
  431.     Link(document, documentToInsert);
  432. }
  433.  
  434.  
  435. /*****************************************************************************
  436.  * 
  437.  * Remove                                                              PRIVATE
  438.  * 
  439.  * Remove a document from any list. Does NOT delete the document from memory.
  440.  *
  441.  *****************************************************************************/
  442. static void Remove(DocumentReference document)
  443. {
  444.     DocumentReference    previous        = GetDocumentPreviousDocument(document);
  445.     DocumentReference    next          = GetDocumentNextDocument(document);
  446.  
  447.     Link(previous, next);
  448.  
  449.     (**document).previous = nil;
  450.     (**document).next     = nil;
  451. }
  452.  
  453.  
  454. /*****************************************************************************
  455.  * 
  456.  * Link                                                                PRIVATE
  457.  * 
  458.  *   Establish a 2-way link between two documents
  459.  *
  460.  *****************************************************************************/
  461. static void Link(DocumentReference previous, DocumentReference next)
  462. {
  463.     (**previous).next = next;
  464.     
  465.     if (next != nil)
  466.         (**next).previous = previous;
  467. }
  468.  
  469. // --------------------------------------------------------------------------
  470.  
  471.  
  472. short GetDocumentNumber(DocumentReference document)
  473. {
  474.     return (**document).documentNumber;
  475. }
  476.  
  477. // --------------------------------------------------------------------------
  478.  
  479. DocumentType GetDocumentType(DocumentReference document)
  480. {
  481.     return (**document).documentType;
  482. }
  483.  
  484. // --------------------------------------------------------------------------
  485.  
  486. void GetDocumentName(DocumentReference document, StringPtr documentName)
  487. {
  488.     PStringCopy((**document).documentName, documentName);
  489. }
  490.  
  491. // --------------------------------------------------------------------------
  492.  
  493. DocumentReference GetDocumentNextDocument(DocumentReference document)
  494. {
  495.     return (**document).next;
  496. }
  497.  
  498. // --------------------------------------------------------------------------
  499.  
  500. DocumentReference GetDocumentPreviousDocument(DocumentReference document)
  501. {
  502.     return (**document).previous;
  503. }
  504.  
  505. // --------------------------------------------------------------------------
  506.  
  507. WindowPtr GetDocumentWindow(DocumentReference document)
  508. {
  509.     return (**document).window;
  510. }
  511.  
  512. // --------------------------------------------------------------------------
  513.  
  514. ElementList GetDocumentElementList(DocumentReference document)
  515. {
  516.     return (**document).elementList;
  517. }
  518.  
  519. // --------------------------------------------------------------------------
  520.  
  521. short GetDocumentMaxWidth(DocumentReference document)
  522. {
  523.     return (**document).maxWidth;
  524. }
  525.  
  526. // --------------------------------------------------------------------------
  527.  
  528. short GetDocumentMaxHeight(DocumentReference document)
  529. {
  530.     return (**document).maxHeight;
  531. }
  532.  
  533. // --------------------------------------------------------------------------
  534.  
  535. unsigned short GetDocumentNumberOfChanges(DocumentReference document)
  536. {
  537.     return (**document).numberOfChanges;
  538. }
  539.  
  540.  
  541. // --------------------------------------------------------------------------
  542.  
  543. void SetDocumentType(DocumentReference document, DocumentType documentType)
  544. {
  545.     (**document).documentType = documentType;
  546. }
  547.  
  548. // --------------------------------------------------------------------------
  549.  
  550. void SetDocumentName(DocumentReference document, ConstStr63Param documentName)
  551. {
  552.     PStringCopy((StringPtr) documentName, (**document).documentName);
  553.  
  554.     if ((**document).window != nil)
  555.     {
  556.         SetWTitle((WindowPtr) (**document).window, documentName);
  557.     }
  558. }
  559.  
  560. // --------------------------------------------------------------------------
  561.  
  562. void SetDocumentNextDocument(DocumentReference document, DocumentReference next)
  563. {
  564.     (**document).next = next;
  565. }
  566.  
  567. // --------------------------------------------------------------------------
  568.  
  569. void SetDocumentPreviousDocument(DocumentReference document, DocumentReference previous)
  570. {
  571.     (**document).previous = previous;
  572. }
  573.  
  574. // --------------------------------------------------------------------------
  575.  
  576. void SetDocumentNumberOfChanges(DocumentReference document, unsigned short numberOfChanges)
  577. {
  578.     (**document).numberOfChanges = numberOfChanges;
  579. }
  580.  
  581. // --------------------------------------------------------------------------
  582.  
  583. void SetDocumentWindow(DocumentReference document, WindowPtr window)
  584. {
  585.     WindowPtr    existingWindow;
  586.  
  587.     existingWindow = (**document).window;
  588.  
  589.     if (existingWindow != window)                                                        // are they different
  590.         if (existingWindow != nil)                                                        // is it currently non-nil?
  591.             DisposeWindow(existingWindow);
  592.         
  593.     (**document).window = window;
  594.     
  595.     if (window != nil)
  596.     {
  597.         SetWRefCon((WindowPtr) window, (long) document);
  598.     }
  599. }
  600.  
  601. // --------------------------------------------------------------------------
  602.  
  603. void SetDocumentElementList(DocumentReference document, ElementList list)
  604. {
  605.     ElementList    existingList = (**document).elementList;
  606.  
  607. /*
  608.     if (existingWindow != list)                                                        // are they different
  609.         if (existingList != nil)                                                        // is it currently non-nil?
  610.             DisposeWindow(existingWindow);
  611. */
  612.         
  613.     (**document).elementList = list;
  614.     
  615. }
  616.  
  617. // --------------------------------------------------------------------------
  618.  
  619. void SetDocumentMaxWidth(DocumentReference document, short maxWidth)
  620. {
  621.     (**document).maxWidth = maxWidth;
  622. }
  623.  
  624. // --------------------------------------------------------------------------
  625.  
  626. void SetDocumentMaxHeight(DocumentReference document, short maxHeight)
  627. {
  628.     (**document).maxHeight = maxHeight;
  629. }
  630.  
  631.  
  632. // --------------------------------------------------------------------------
  633.  
  634.  
  635.